首页

欢迎

 

Welcome

欢迎来到这里, 这是一个学习数学、讨论数学的网站.

转到问题

请输入问题号, 例如: 2512

IMAGINE, THINK, and DO
How to be a scientist, mathematician and an engineer, all in one?
--- S. Muthu Muthukrishnan

Local Notes

Local Notes 是一款 Windows 下的笔记系统.

Local Notes 下载

Sowya

Sowya 是一款运行于 Windows 下的计算软件.

详情

下载 Sowya.7z (包含最新版的 Sowya.exe and SowyaApp.exe)


注: 自 v0.550 开始, Calculator 更名为 Sowya. [Sowya] 是吴语中数学的发音, 可在 cn.bing.com/translator 中输入 Sowya, 听其英语发音或法语发音.





注册

欢迎注册, 您的参与将会促进数学交流. 注册

在注册之前, 或许您想先试用一下. 测试帐号: usertest 密码: usertest. 请不要更改密码.


我制作的 slides

Problem

随机显示问题

Problèmes d'affichage aléatoires

计算数学 >> 离散数学 >> 图论
Questions in category: 图论 (Graph Theory).

Floyd 算法的理解

Posted by haifeng on 2019-04-25 21:10:32 last update 2019-04-26 12:47:26 | Answers (0)


Floyd 算法是图论中计算两两顶点之间最短路径的算法. 算法复杂度为 $O(N^3)$.


设 $G=(V,E)$ 是一个带权图(有向或者无向). $n=|V|$, $W$ 是它的权矩阵. 顶点集合 $V=\{v_1,v_2,\ldots,v_n\}$, 有时不妨记为 $V=\{1,2,\ldots,n\}$.

通过下面的算法计算距离矩阵 $D=(d_{ij})_{n\times n}$ 和路径矩阵 $R=(r_{ij})_{n\times n}$.

其中 $d_{ij}=\text{dist}(v_i,v_j)$. 而 $r_{ij}$ 表示顶点 $v_i$ 到 $v_j$ 的最短路径中经过的某个顶点.

 

 

 

(1)第一幅图. 线段 $i--j$

$d_{ij}^{(0)}=d(i,j)$ 指顶点 $v_i$ 和 $v_j$ 之间的权, 初始矩阵 $D^{(0)}=(d_{ij}^{(0)})=W$.

(2) 第二幅图. 三角形 $ij1$. 在 $v_i$ 和 $v_j$ 之间插入了顶点 $v_1$.

\[
d_{ij}^{(1)}=\min\{d_{ij}^{(0)},d_{i1}^{(0)}+d_{1j}^{(0)}\}
\] 

也就是说, 从 $v_i$ 到 $v_j$ 的最短路径必从三角形 $ij1$ 的边界(boundary)上经过.

 

(3) 第三幅图. 四面体 $ij12$(也就是三维单形)

从 $v_i$ 到 $v_j$ 的最短路径, 先考虑从 $\triangle i21$ 的边界(boundary)经过, 然后从 $\triangle 2j1$ 的边界(boundary)经过. 将它们的和与 $d_{ij}^{(1)}$ 作比较. 取长度较小的路径.

实际上, 从 $v_i$ 到 $v_j$ 的最短路径, 必从四面体 $ij12$ 的三个面 $i21$, $2j1$, $ij1$ 所组成的复形的骨架上经过. 当然这样的话, 已经将三角形 $ij2$ 的边界考虑了. 因此, 从 $v_i$ 到 $v_j$ 的最短路径必从四面体 $ij12$ 的边界上经过.

 

其余的, 可从高维上类似理解.


 

以下是 MATLAB 代码

 

% page 93.
% filename: floyd.m
function [D,R] = floyd(A)
n=size(A,1); % n 等于矩阵 A 的行数.
D=A
for i=1:n
    for j=1:n
        R(i,j)=j;
    end
end
R

for k=1:n
    for i=1:n
        for j=1:n
            if D(i,k)+D(k,j) < D(i,j)
                D(i,j)=D(i,k)+D(k,j);
                R(i,j)=R(i,k);
            end
        end
    end
    k
    D
    R
    '-----------------------'
end

 

注意:

  • $k$ 是指插入点的标号, 因此关于 $k$ 的循环一定要放在最外层.
  • 其中的 R(i,j)=R(i,k); 也可以换成 R(i,j)=k; 但是要注意, 如果是用C/C++编程, 那么指标 k 从0 开始的, 因此必须要前后一致.